Fce z C - DLL

Otázka od: Blazek Jaroslav

27. 9. 2002 15:36

Ahoj,

mam fci v Cckovskem DLL

extern "C" __declspec(dllexport) bool __fastcall MojeFce(const char *AStringIN,
char *AStringOUT);

" MojeDLL.dll >> MojeDLL.def "

LIBRARY MOJEDLL.DLL

EXPORTS
    @MojeFce @1 ; MojeFce

a potrebuju ji volat v Delphi
zkousel jsem toto, ale nejak to nechodi, stale mi to hlasi ze dana fce v DLL
neni

A. function MojeFce(const AStringINr:PChar; AStringOUT:PChar):boolean; cdecl;
external 'MojeDLL.dll';
nebo
B. function MojeFce(const AStringINr:PChar; AStringOUT:array of char):boolean;
cdecl; external 'MojeDLL.dll';
nebo i druhy parametr jako " var "

nevim co mam pouzit za typ druheho parametru, jak pri deklaraci, tak pro volani

zkousel jsem pro volani

1. Buffer:array of char;
    SetLength(Buffer, DELKA);
2. Buffer:array [0..DELKA] of char;
3. Buffer:string;
     PChar(Buffer)

vzdy pro prislusne deklarace fce, vzdycky to proslo, ale po spusteni to
nahlasilo, ze fce v dynamicke knihovne neni, pritom toto v BCB mi funguje bez
problemu

ty retezce v pascalu s venkovni komunikaci me jednou zabijou  

chtel jsem si prepsat tento svuj kod do Delphi, ale zasek jsem se na deklaraci
na typu < ukazatel na fci >, to mi nejak uchazi....

< C++ >
typedef bool __fastcall (* TMojeFce)(const char *, char *);

 HINSTANCE hInst = LoadLibrary("MojeDLL.dll");
 if (hInst)
  {
   TMojeFce MojeFce;
   MojeFce = (TMojeFce)GetProcAddress(hInst,"@MojeFce");
   if (MojeFce)
    {
     char *Buffer = new char[DELKA + 1];
     try
      {
       if (MojeFce("Nejaky text", Buffer))
        ShowMessage(Buffer);
      }
     __finally
      {
       delete []Buffer;
      }
    }
   FreeLibrary(hInst);
  }
</ C++ >


S pozdravem

Bc. Jaroslav Blazek
Access-IT Ceska Lipa
mailto:jaroslav.blazek@access-it.cz
http://www.access-it.cz
ICQ# : 133673990
+420605/813644

Odpovedá: Dalibor Toman

27. 9. 2002 16:07

>mam fci v Cckovskem DLL
>
>extern "C" __declspec(dllexport) bool __fastcall MojeFce(const char
*AStringIN, char *AStringOUT);
>" MojeDLL.dll >> MojeDLL.def "

>EXPORTS
> @MojeFce @1 ; MojeFce

>a potrebuju ji volat v Delphi
>zkousel jsem toto, ale nejak to nechodi, stale mi to hlasi ze dana
fce v DLL neni

bodejt kdyz ta funkce podle vseho neni exportovana pod jmenem ale pod
cislem (1). Bud predelat CCko aby se takova cunarna nekonala nebo v
Delphi v deklaraci pripsat prislusnou direktivu (ted nevim jetli to je
'index' nebo neco jineho.

pokud se v CC exportuje jmeno je jeste nutne zjistit jak je to s
dekoraci - ruzne kompilatory pridavaji ruzne veci kolem jmena
(podtrzitka zleva specifikace parametru za '@' zprava). Vliv na to ma
spousta veci (at ten __declspec ci *.DEF file). Je docela sranda
napsat kod ktery M$ a Borland C vyexportuje stejne (pouzitelne pro
Pascal)

>A. function MojeFce(const AStringINr:PChar;
AStringOUT:PChar):boolean; cdecl; external 'MojeDLL.dll';
>nebo
>B. function MojeFce(const AStringINr:PChar; AStringOUT:array of
char):boolean; cdecl; external 'MojeDLL.dll';
>nebo i druhy parametr jako " var "

zalezi na tom jak s tim druhym parametrem budes zachazet. Muzes
vyrobit primo nejaky typ (TBuff = Array[0..100] of Char) nebo nechat
bez typu atd

Function MojeFce(const AStringINr:Pointer : PChar; VAR AStringOUT ) :
BOOL; cdecl; external 'MojeDLL.dll index 1';

Boolean bych asi nahradil windowsim BOOL (pokud ta funkce opravdu neni
deklarovana tak aby vracela byte). Nevim si rady s __fastcall - je
treba se podivat do helpu k tomu CCku co to vlastne dela

PS: v helpu jsem nejak zminku o 'index' pri importu nenasel - taze to
mozna nepujde prelozit  


>problem je zrejme v tom
>vzdy pro prislusne deklarace fce, vzdycky to proslo, ale po spusteni
to nahlasilo,
>ze fce v dynamicke knihovne neni, pritom toto v BCB mi funguje bez
problemu

viz vyse - je treba zarucit , ze export i import pouivaji stejne
jmeno/index funkce

>ty retezce v pascalu s venkovni komunikaci me jednou zabijou  

u Z-termitaed stringu jde jen o buffer. Pokud se me povede
usporadat si v hlave ty ceckovsky pointry na pointry pak
to uz vetsinou neni problem  

>chtel jsem si prepsat tento svuj kod do Delphi, ale zasek
>jsem se na deklaraci na typu < ukazatel na fci >, to mi nejak
uchazi....

pokus o prepis do Pascalu (bez kontroly kompilatorem)

TYPE
 TMojeFunkce = Function(In : PChar; Out : Pointer) : BOOL;

Procedure UseTheFunction;
VAR
 F : TMojeFunkce;
 H : THandle;
 buffer : array[0...1000] of Char;
begin
  H := LoadLibrary('mojedll.dll');
  if H = INVALID_HANDLE_VALUE then
   Exit;
  @F := GetProcAddress('skjutecne_jmeno_funkce');
  if @F <> NIL then
 begin
  F('nejaky text',@buffer);
 end
end;

--

pokud chces 'buffer' dynamicky alokovat pak (a bude to tedy pinter na
neco) pak volas
  F('nejaky text',buffer);

Zdravi
D. Toman

Odpovedá: Ondrej Kelle

27. 9. 2002 17:11

> extern "C" __declspec(dllexport) bool __fastcall
> MojeFce(const char *AStringIN, char *AStringOUT);

> a potrebuju ji volat v Delphi
> zkousel jsem toto, ale nejak to nechodi, stale mi to hlasi ze
> dana fce v DLL neni

To znamena, ze funkcia s menom 'MojeFce' nebola v tej DLL exportovana.
C++ kompilatory maju niekedy vo zvyku menit vysledne mena funkcii (tzv. name
mangling). Skutocne mena v DLL si mozes zistit napr. pomocou tdump alebo
Dependency Walker.
V tom C++ priklade to mas dokonca uvedene v kode: '@MojeFce'  

Takze:

function MojeFce(AStringIn, AStringOut: PChar): BOOL; external 'MojeDLL.dll'
name '@MojeFce';

pripadne mozes linkovat pomocou indexu:

function MojeFce(AStringIn, AStringOut: PChar): BOOL; external 'MojeDLL.dll'
index 0;

Dalej, "cdecl" nie je myslim ta spravna calling convention; ekvivalentom pre
Borland "__fastcall" je v Delphi tusim "register" (co je default).

> typedef bool __fastcall (* TMojeFce)(const char *, char *);
>
> HINSTANCE hInst = LoadLibrary("MojeDLL.dll");
> if (hInst)
> {
> TMojeFce MojeFce;
> MojeFce = (TMojeFce)GetProcAddress(hInst,"@MojeFce");
> if (MojeFce)
> {
> char *Buffer = new char[DELKA + 1];
> try
> {
> if (MojeFce("Nejaky text", Buffer))
> ShowMessage(Buffer);
> }
> __finally
> {
> delete []Buffer;
> }
> }
> FreeLibrary(hInst);
> }

type
  TMojeFce = function(AStringIn, AStringOut: PChar): BOOL;

var
  hInst: HINSTANCE;
  MojeFce: TMojeFce;
  Buffer: array[0..DELKA + 1] of Char;
begin
  hInst := LoadLibrary('MojeDLL.dll');
  if hInst <> 0 then
    try
      @MojeFce := GetProcAddress(hInst, '@MojeFce');
      if @MojeFce <> nil then
        if MojeFce('Nejaky text', Buffer) then
          ShowMessage(Buffer);
    finally
      FreeLibrary(hInst);
    end;
end;

HTH
TOndrej

Odpovedá: Ondrej Kelle

27. 9. 2002 17:50

> function MojeFce(AStringIn, AStringOut: PChar): BOOL;
> external 'MojeDLL.dll' name '@MojeFce';
>
> pripadne mozes linkovat pomocou indexu:
>
> function MojeFce(AStringIn, AStringOut: PChar): BOOL;
> external 'MojeDLL.dll' index 0;

Este som zabudol dopisat, nema zmysel linkovat tu DLL staticky, ked ju potom
natahujes dynamicky.
Takze tieto external deklaracie vymaz a pouzi len ten kod s
LoadLibrary/GetProcAddress.

TOndrej

Odpovedá: Petr Vones

27. 9. 2002 18:24

From: "Dalibor Toman" <dtoman@fortech.cz>
> >EXPORTS
> > @MojeFce @1 ; MojeFce
>
> bodejt kdyz ta funkce podle vseho neni exportovana pod jmenem ale pod
> cislem (1). Bud predelat CCko aby se takova cunarna nekonala nebo v

Neni to 1 spise hint ? Jinak funkce by ve Win32 mely byt exportovany zasadne
jen jmenem.

Petr Vones

Odpovedá: Blazek Jaroslav

27. 9. 2002 20:19

Ahoj,

> dtoman@fortech.cz 27.9.02 16:58 >>>
>extern "C" __declspec(dllexport) bool __fastcall MojeFce(const char
*AStringIN, char *AStringOUT);
>" MojeDLL.dll >> MojeDLL.def "

>EXPORTS
> @MojeFce @1 ; MojeFce

>bodejt kdyz ta funkce podle vseho neni exportovana pod jmenem ale pod
>cislem (1). Bud predelat CCko aby se takova cunarna nekonala nebo v
>Delphi v deklaraci pripsat prislusnou direktivu (ted nevim jetli to je
>'index' nebo neco jineho.

tak to asi ne.....ta fce tam je a jmenuje se MojeFce, v BCB ji normalne nactu
toto je vypis z utilitky impdef.exe, ktera je soucasti Borlandu

impdef.exe MojeDLL.def MojeDLL.dll

>pokud se v CC exportuje jmeno je jeste nutne zjistit jak je to s
>dekoraci - ruzne kompilatory pridavaji ruzne veci kolem jmena
>(podtrzitka zleva specifikace parametru za '@' zprava). Vliv na to ma
>spousta veci (at ten __declspec ci *.DEF file). Je docela sranda
>napsat kod ktery M$ a Borland C vyexportuje stejne (pouzitelne pro
>Pascal)

od toho tam mam < extern "C" ... > tak aby se tak nedelo
pokud bych tam mel < _export > nebo < extern "C++" >, tak ano fci budu mit
ulozenou treba takto

EXPORTS
    @MojeFce$qqrpxct1pc @1 ; __fastcall MojeFce(const char *, char *)

>Nevim si rady s __fastcall - je treba se podivat do helpu k tomu CCku co to
vlastne dela

je to vlastne konverze volani fci v BCB, tudiz i rychlejsi pristup k temto
fcim, rika kompilatoru jak ma zachazet se zasobnikem

>chtel jsem si prepsat tento svuj kod do Delphi, ale zasek
>jsem se na deklaraci na typu < ukazatel na fci >, to mi nejak
uchazi....

>TYPE
> TMojeFunkce = Function(In : PChar; Out : Pointer) : BOOL;

tohle jsem nedovedl napsat, proste jako Cckari mi chybi zaklady paskalu

jen jsem to prepsal na

type
  TMojeFce = function (const AStringIN : PChar; AStringOUT : PChar);

> F('nejaky text',@buffer);

jen toto bych poopravil na

var Buffer : array [0..DELKA + 1] of Char;

F(PChar('nejaky text'), Buffer);


S pozdravem

Bc. Jaroslav Blazek
Access-IT Ceska Lipa
mailto:jaroslav.blazek@access-it.cz
http://www.access-it.cz
ICQ# : 133673990
+420605/813644

Odpovedá: Blazek Jaroslav

27. 9. 2002 19:25

Ahoj,

> O.Kelle@digitalpublishing.de 27.9.02 17:06 >>>
>To znamena, ze funkcia s menom 'MojeFce' nebola v tej DLL exportovana.
>C++ kompilatory maju niekedy vo zvyku menit vysledne mena funkcii (tzv. name
>mangling). Skutocne mena v DLL si mozes zistit napr. pomocou tdump alebo
>Dependency Walker.
>V tom C++ priklade to mas dokonca uvedene v kode: '@MojeFce'  

to same co jsem psal < D. Tomanovi > s < extern "C++" > a < _export >

>type
> TMojeFce = function(AStringIn, AStringOut: PChar): BOOL;

>var
> hInst: HINSTANCE;

na tohle mi nejak D5 rvalo, ze < HINSTANCE > nezna a nenalezl jsem k tomu
nejaky hlavickovy soubor, tak jsem to nahradil < LongWord >

> if MojeFce('Nejaky text', Buffer) then

take bych mozna trochu poopravil, jinak to nebere

 if MojeFce(PChar('Nejaky tex'), Buffer) then

ale jinak diky vsem, uz mi to chodi pomoci dynamickeho natahnuti DLLka

S pozdravem

Bc. Jaroslav Blazek
Access-IT Ceska Lipa
mailto:jaroslav.blazek@access-it.cz
http://www.access-it.cz
ICQ# : 133673990
+420605/813644

Odpovedá: Blazek Jaroslav

27. 9. 2002 19:27

Ahoj,

> O.Kelle@digitalpublishing.de 27.9.02 17:10 >>>
>Este som zabudol dopisat, nema zmysel linkovat tu DLL staticky, ked ju potom
>natahujes dynamicky.
>Takze tieto external deklaracie vymaz a pouzi len ten kod s
>LoadLibrary/GetProcAddress.

to samozrejme ne.....ja jsem si chtel vyzkouset obe varianty, jak dynamicky,
tak staticky


S pozdravem

Bc. Jaroslav Blazek
Access-IT Ceska Lipa
mailto:jaroslav.blazek@access-it.cz
http://www.access-it.cz
ICQ# : 133673990
+420605/813644

Odpovedá: Dalibor Toman

30. 9. 2002 11:22

>> if MojeFce('Nejaky text', Buffer) then
>take bych mozna trochu poopravil, jinak to nebere
>
> if MojeFce(PChar('Nejaky tex'), Buffer) then

to by nemelo hrat roli. Kompilator vi jak s konstantnim textem
zachazet

D. Toman


Odpovedá: Dalibor Toman

30. 9. 2002 11:38


>>EXPORTS
>> @MojeFce @1 ; MojeFce

>>bodejt kdyz ta funkce podle vseho neni exportovana pod jmenem ale
pod
>>cislem (1). Bud predelat CCko aby se takova cunarna nekonala nebo v
>>Delphi v deklaraci pripsat prislusnou direktivu (ted nevim jetli to
je
>>'index' nebo neco jineho.
>
>tak to asi ne.....ta fce tam je a jmenuje se MojeFce, v BCB ji
normalne nactu
>toto je vypis z utilitky impdef.exe, ktera je soucasti Borlandu
>
>impdef.exe MojeDLL.def MojeDLL.dll

s tim indexem jsem asi nemel pravdu. Ale stejne bych se alespon text
viewerem podival na DLLko a hledal text 'MojeFce'. POkud tam nebude je
to problem. Pokud tam je nemeli by kolem nej byt podtrzitka a
zavinace. Nejjistejsi je vzit nejaky PE viewer a podivat se na jmena
exportovanych funkci. Tak zjistis presne jak to CCko exportuje. Pred
par mesicema jsem se s tim dost nazlobil (nenasel jsem zapis deklarace
exportovanych funkci pouzitelny jak pro MS C++ tak pro BC++. Nakonec
jsem, pouzil neco jako:

#ifdef __BCPLUSPLUS__
#define PPAPIENTRY _export _stdcall
#else
#define PPAPIENTRY __declspec( dllexport ) __stdcall
#endif

vlastni pouziti pak:

extern "C" HRESULT APIENTRY PPP_POP3_Scan(DWORD MessageHandle);

*.DEF file jsem nepouzil (byly s tim taky problemy, udrzba atd)

mozna to slo vyresit lip. Ale ja pro zmenu zase nejsem Cckar a
spokojil jsem se s prvnim vyhovujicim resenim..


D. Toman


Odpovedá: Dalibor Toman

30. 9. 2002 12:26

>function Fce(const AParam:string,...
>...
> MojeFce(AParam,...)
>
>tak to hazi chybu < Incompatible types : 'String' and 'PChar' >

jasne - tam je to pretypovani nutne uvest (ale opet ne v pripade, ze
te funkci predavas textovy literal)


D. Toman


Odpovedá: Blazek Jaroslav

30. 9. 2002 13:00

Ahoj,

> dtoman@fortech.cz 30.9.02 10:08 >>>
>> if MojeFce('Nejaky text', Buffer) then
>take bych mozna trochu poopravil, jinak to nebere
>
> if MojeFce(PChar('Nejaky tex'), Buffer) then

>to by nemelo hrat roli. Kompilator vi jak s konstantnim textem
>zachazet

Aha....no takhle to opravdu jde, ale jakmile mam

function Fce(const AParam:string,...
...
 MojeFce(AParam,...)

tak to hazi chybu < Incompatible types : 'String' and 'PChar' >


S pozdravem

Bc. Jaroslav Blazek
Access-IT Ceska Lipa
mailto:jaroslav.blazek@access-it.cz
http://www.access-it.cz
ICQ# : 133673990
+420605/813644